{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "f04dd603-a2d1-48ce-8c17-9f1dba8de1ee",
   "metadata": {},
   "source": [
    "Chapter 07\n",
    "\n",
    "# 鸡兔同笼-用numpy.linalg.solve()求解\n",
    "《线性代数》 | 鸢尾花书：数学不难"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ccafb456-2453-4c82-8a65-b1963a370cb2",
   "metadata": {},
   "source": [
    "该代码利用线性代数的方法求解“鸡兔同笼”问题，这是一个典型的线性方程组求解问题。\n",
    "\n",
    "---\n",
    "\n",
    "## **数学建模**\n",
    "设鸡的数量为 \\( x_1 \\)，兔的数量为 \\( x_2 \\)。根据问题描述，我们可以列出如下方程组：\n",
    "\n",
    "$$\n",
    "\\begin{cases}\n",
    "x_1 + x_2 = 35 \\quad &\\text{(总数量方程)} \\\\\n",
    "2x_1 + 4x_2 = 94 \\quad &\\text{(总腿数方程)}\n",
    "\\end{cases}\n",
    "$$\n",
    "\n",
    "该方程组可用矩阵形式表示为：\n",
    "\n",
    "$$\n",
    "A \\mathbf{x} = \\mathbf{b}\n",
    "$$\n",
    "\n",
    "其中：\n",
    "$$\n",
    "A = \\begin{bmatrix} 1 & 1 \\\\ 2 & 4 \\end{bmatrix}, \\quad\n",
    "\\mathbf{x} = \\begin{bmatrix} x_1 \\\\ x_2 \\end{bmatrix}, \\quad\n",
    "\\mathbf{b} = \\begin{bmatrix} 35 \\\\ 94 \\end{bmatrix}\n",
    "$$\n",
    "\n",
    "目标是求解向量 \\( \\mathbf{x} \\)，即：\n",
    "\n",
    "$$\n",
    "\\mathbf{x} = A^{-1} \\mathbf{b}\n",
    "$$\n",
    "\n",
    "---\n",
    "\n",
    "## **代码解析**\n",
    "1. **定义系数矩阵 $A$ 和常数向量 $b$**：\n",
    "   - $A$ 表示系数矩阵，描述变量 $x_1, x_2$ 在方程中的系数。\n",
    "   - $b$ 是常数列向量，表示等式右侧的数值。\n",
    "\n",
    "2. **调用 `numpy.linalg.solve(A, b)`**：\n",
    "   - `numpy.linalg.solve(A, b)` 通过高斯消元或 LU 分解的方式求解线性方程组 $A\\mathbf{x} = \\mathbf{b}$。\n",
    "   - 该方法的计算过程等价于计算：\n",
    "     $$\n",
    "     \\mathbf{x} = A^{-1} \\mathbf{b}\n",
    "     $$\n",
    "     但 `numpy.linalg.solve` 采用更高效的数值方法，而非直接计算矩阵逆。\n",
    "\n",
    "3. **得到解 $x$**：\n",
    "   - 计算得到 $x = [x_1, x_2]^T$，即鸡的数量和兔的数量。\n",
    "\n",
    "---\n",
    "\n",
    "## **矩阵求解过程**\n",
    "通过高斯消元法或 LU 分解，矩阵 $A$ 可分解为：\n",
    "\n",
    "$$\n",
    "A = L U\n",
    "$$\n",
    "\n",
    "其中：\n",
    "- $L$ 是一个下三角矩阵。\n",
    "- $U$ 是一个上三角矩阵。\n",
    "\n",
    "然后利用前代回代的方法求解 \\( A\\mathbf{x} = \\mathbf{b} \\)，最终得到 \\( \\mathbf{x} \\)。\n",
    "\n",
    "如果直接计算逆矩阵：\n",
    "$$\n",
    "A^{-1} = \\begin{bmatrix} 2 & -0.5 \\\\ -1 & 0.5 \\end{bmatrix}\n",
    "$$\n",
    "\n",
    "那么：\n",
    "$$\n",
    "\\mathbf{x} = A^{-1} \\mathbf{b} = \\begin{bmatrix} 2 & -0.5 \\\\ -1 & 0.5 \\end{bmatrix} \\begin{bmatrix} 35 \\\\ 94 \\end{bmatrix}\n",
    "$$\n",
    "\n",
    "计算得到：\n",
    "$$\n",
    "\\mathbf{x} = \\begin{bmatrix} 23 \\\\ 12 \\end{bmatrix}\n",
    "$$\n",
    "\n",
    "这表明鸡的数量为 23 只，兔的数量为 12 只，即：\n",
    "\n",
    "$$\n",
    "x_1 = 23, \\quad x_2 = 12\n",
    "$$\n",
    "\n",
    "---\n",
    "\n",
    "## **总结**\n",
    "该代码使用 `numpy.linalg.solve(A, b)` 直接求解线性方程组，而不计算矩阵的逆。这样可以提高计算效率，并避免数值误差。最终，我们得到的解是：\n",
    "\n",
    "$$\n",
    "x_1 = 23, \\quad x_2 = 12\n",
    "$$\n",
    "\n",
    "这意味着在鸡兔同笼问题中，共有 23 只鸡和 12 只兔子。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1d427f21-15b6-4155-9eea-ba333621cfaf",
   "metadata": {},
   "source": [
    "## 初始化"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "d530bc5e-a5b5-41cf-92e4-461541be8fc2",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "dcea75fb-c19a-4f90-a0e9-b8556344174b",
   "metadata": {},
   "source": [
    "## 鸡兔同笼系数矩阵"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "f1044cb0-92c2-4e07-8b42-b5571dfc9101",
   "metadata": {},
   "outputs": [],
   "source": [
    "A = np.array([[1, 1], \n",
    "              [2, 4]])\n",
    "# a_1, chicken \n",
    "# a_2, rabbit"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6d759117-5643-4b86-a795-1ebf15aa254b",
   "metadata": {},
   "source": [
    "## 常数列向量"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "954b7525-dcef-47cb-af13-40c741ca3891",
   "metadata": {},
   "outputs": [],
   "source": [
    "b = np.array([[35],\n",
    "              [94]])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7799aec4-4734-49f7-b0c4-2d34344aa7be",
   "metadata": {},
   "source": [
    "## 用numpy.linalg.solve()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "aa3dd5d6-6437-4775-9611-64e4fbb5ef65",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[23.],\n",
       "       [12.]])"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x = np.linalg.solve(A, b)\n",
    "x"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "03232b1c-9ff6-41a6-8eb9-b5f98c289f77",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "070c3389-8048-43a3-baa7-6666009bce96",
   "metadata": {},
   "source": [
    "作者\t**生姜DrGinger**  \n",
    "脚本\t**生姜DrGinger**  \n",
    "视频\t**崔崔CuiCui**  \n",
    "开源资源\t[**GitHub**](https://github.com/Visualize-ML)  \n",
    "平台\t[**油管**](https://www.youtube.com/@DrGinger_Jiang)\t\t\n",
    "\t\t[**iris小课堂**](https://space.bilibili.com/3546865719052873)\t\t\n",
    "\t\t[**生姜DrGinger**](https://space.bilibili.com/513194466)  "
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python [conda env:base] *",
   "language": "python",
   "name": "conda-base-py"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
